package cn.yshujia.repository;

import cn.yshujia.domain.dto.PageDTO;
import cn.yshujia.domain.entity.Resources;
import cn.yshujia.domain.vo.LabelVO;
import cn.yshujia.domain.vo.PageVO;
import cn.yshujia.domain.vo.ResourcesVO;
import cn.yshujia.mapper.ResourcesMapper;
import cn.yshujia.service.impl.LabelServiceImpl;
import cn.yshujia.transform.ResourcesTransform;
import cn.yshujia.utils.PageUtils;
import cn.yshujia.utils.RandomUtils;
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import jakarta.annotation.Resource;
import org.springframework.data.redis.core.RedisTemplate;
import org.springframework.scheduling.annotation.Async;
import org.springframework.stereotype.Repository;
import org.springframework.util.ObjectUtils;

import java.time.Duration;
import java.util.ArrayList;
import java.util.List;
import java.util.Map;
import java.util.Set;

/**
 * @author YShuJia
 * @create 2024/11/30
 * @description ResourcesRepository
 */

@Repository
public class ResourcesRepository {
	
	@Resource
	RedisTemplate<String, ResourcesVO> redis;
	
	@Resource
	ResourcesMapper mapper;
	
	@Resource
	LabelServiceImpl labelService;
	
	public static final String LIST = "resources:label:";
	
	public static final Duration DURATION = Duration.ofDays(3L);
	
	public PageVO<ResourcesVO> selectPageByLabelId(PageDTO dto) {
		Map<String, Object> map = dto.getParam();
		if (null == map || null == map.get("labelId")) {
			return new PageVO<>();
		}
		long labelId = Long.parseLong(map.get("labelId").toString());
		String KEY = LIST + labelId;
		
		long start = dto.getCurrent() > 0 ? (long) (dto.getCurrent() - 1) * dto.getSize() : 0;
		long end = start + dto.getSize() - 1;
		// 获取缓存
		List<ResourcesVO> voList = redis.opsForList().range(KEY, start, end);
		if (!ObjectUtils.isEmpty(voList)) {
			return PageUtils.getPage(dto, voList, redis.opsForList().size(KEY));
		}
		// 获取数据库数据
		LambdaQueryWrapper<Resources> wrapper = new LambdaQueryWrapper<>();
		wrapper.eq(Resources::getLabelId, labelId);
		
		List<Resources> list = mapper.selectList(wrapper);
		// 获取VO
		voList = createVOList(list);
		if (!ObjectUtils.isEmpty(voList)) {
			set(voList, KEY);
		}
		return PageUtils.getPage(dto, voList);
	}
	
	public ResourcesVO selectRandomIcon() {
		List<ResourcesVO> voList = redis.opsForList().range(LIST + "10000001", 0, -1);
		if (!ObjectUtils.isEmpty(voList)) {
			return voList.get(RandomUtils.getRandom(voList.size()));
		}
		List<Resources> list = mapper.selectList(new LambdaQueryWrapper<Resources>()
				.eq(Resources::getLabelId, 10000001));
		if (!ObjectUtils.isEmpty(list)) {
			return ResourcesTransform.entity2VO(list.get(RandomUtils.getRandom(list.size())));
		}
		return null;
	}
	
	public ResourcesVO selectRandomWall() {
		List<ResourcesVO> voList = redis.opsForList().range(LIST + "10000002", 0, -1);
		if (!ObjectUtils.isEmpty(voList)) {
			return voList.get(RandomUtils.getRandom(voList.size()));
		}
		List<Resources> list = mapper.selectList(new LambdaQueryWrapper<Resources>()
				.eq(Resources::getLabelId, 10000002));
		if (!ObjectUtils.isEmpty(list)) {
			return ResourcesTransform.entity2VO(list.get(RandomUtils.getRandom(list.size())));
		}
		return null;
	}
	
	public List<ResourcesVO> createVOList(List<Resources> list) {
		List<ResourcesVO> voList = new ArrayList<>();
		if (!ObjectUtils.isEmpty(list)) {
			for (Resources resources : list) {
				ResourcesVO vo = ResourcesTransform.entity2VO(resources);
				LabelVO label = labelService.selectById(resources.getLabelId());
				if (null != label) {
					vo.setLabel(label);
				}
				voList.add(vo);
			}
		}
		return voList;
	}
	
	
	@Async ("Task")
	public void set(List<ResourcesVO> value, String key) {
		redis.opsForList().rightPushAll(key, value);
		redis.opsForList().getOperations().expire(key, DURATION);
	}
	
	@Async ("Task")
	public void del() {
		Set<String> keys = redis.keys(LIST + "*");
		redis.delete(keys);
	}
}
